﻿using System;
using System.Collections.Generic;

namespace Hydrogen.MathExt.Expression.Functions.Operators
{
    /// <summary>
    /// 二元运算符
    /// </summary>
    public abstract class OperatorBinaryBase
    {
        /// <summary>
        /// 运算优先级
        /// </summary>
        public abstract int Precedence { get; }
        public abstract double Evaluate(double left, double right);


        #region static
        private static Dictionary<string, OperatorBinaryBase> _binaryOperatorDic = new Dictionary<string, OperatorBinaryBase>()
        {
            {"+",new OperatorAdd() },
            {"-",new OperatorSubtract() },
            {"*",new OperatorMultiplie() },
            {"/",new OperatorDivide() },
            {"%",new OperatorMod() },
            {"^",new OperatorPow() },
        };

        /// <summary>
        /// 是运算符吗
        /// </summary>
        public static bool IsOperator(string key) => _binaryOperatorDic.ContainsKey(key);
        public static bool TryGetOperator(string key, out OperatorBinaryBase result) => _binaryOperatorDic.TryGetValue(key, out result);

        public static void RegistOperator(string key, OperatorBinaryBase value, bool force = false)
        {
            if (string.IsNullOrEmpty(key)) return;

            var b = IsOperator(key);
            if (b && !force)
            {
                throw new ArgumentException($"已经注册过运算符\"{key}\"，不建议覆盖已有的运算符。如果想要覆盖已有的运算符，请传入参数<force=true>来强制覆盖");
            }

            _binaryOperatorDic[key] = value;
        }
        public static List<string> GetSupportedConstants() => new List<string>(_binaryOperatorDic.Keys);

        /// <summary>
        /// 获取运算优先级
        /// </summary>
        public static int GetPrecedence(string key)
        {
            if (!TryGetOperator(key, out var op)) return 0;
            return op.Precedence;
        }
        #endregion
    }
}
